#pragma once
#include "MLSScanner.h"
#include "RichWriter.h"
#include "RTFWriter.h"
#include "MLSChain.h"

#define MLS_MAX_PARA 10
#define MLS_MAX_LANG 5
#define MAX_COMM 30
#define MAX_TBLCOLS 30

class CMLSParser :
	protected  CMLSScanner
{
public:
	enum MPError{mpe_none,mpe_file,mpe_Extra,mpe_Command
	,mpe_ParaMiss,mpe_Embed,mpe_Type,mpe_Expected};

	enum EmbedType
	{et_Footnote,et_HeadFoot,et_Paragraph,et_Table,et_Block};

	enum MLSCommand {
		mlscm_Unknown = -1,
		mlscm_NJ = 0x00,
		mlscm_LJ = 0x01,
		mlscm_RJ = 0x02,
		mlscm_CJ = 0x03,
		mlscm_BJ = 0x04,
		mlscm_BF = 0x05,
		mlscm_FN = 0x06,
		mlscm_HE = 0x07,
		mlscm_FT = 0x08,
		mlscm_TB = 0x09,
		mlscm_PA = 0x0A,
		mlscm_PN = 0x0B,
		mlscm_PC = 0x0C,//End of important commands
		mlscm_BM = 0x0D,
		mlscm_CS = 0x0E,
		mlscm_LI = 0x0F,
		mlscm_PI = 0x10,
		mlscm_LM = 0x11,
		mlscm_LS = 0x12,
		mlscm_NF = 0x13,
		mlscm_NS = 0x14,
		mlscm_NT = 0x15,
		mlscm_PS = 0x16,
		mlscm_RI = 0x17,
		mlscm_RM = 0x18,
		mlscm_SS = 0x19,
		mlscm_ST = 0x1A,
		mlscm_TM = 0x1B,
		mlscm_UO = 0x1C,
		mlscm_UW = 0x1D
	};

protected:

	struct CommandRulesItem
	{
		char CommandText[3];
		BOOL Embedable;
	};
	struct TableColumn
	{
		//TableColumn():Width(-1){}
		int Width;
		CRichWriter::RichJust Just;
	};
public:
	CMLSParser(void): ArabicFont(0),
		EnglishFont(0),CopticFont(3),GreekFont(4),Underline(FALSE),bTaleDefined(FALSE),
		Embed(et_Block),PageCode('#'),CurrentJust(CRichWriter::NotSpec),
		TextColor(RGB(0,0,0)),CommandsColor(RGB(255,51,0)),SeparatorColor(RGB(0,102,255)),
		bGenerateSeparator(TRUE), NotifyError(DefaultHandle),
		Roman(0),Arabic(1),Coptic(2),Greek(3)
	{}

	~CMLSParser(void){}
	BOOL ParseFile(CStringA FileName, CRichWriter* Target);
	BOOL ParseChain(CMLSChain* Source, CRichWriter* Target);
	BOOL ParseSource(CStringA FileName, CRichWriter* Target);
	//MPError GetError(){return Error;}
	//CStringA GetErrMsg();
	void SetErrorEvent(BOOL (*Handler) (MPError nError, LPCSTR Filename, ULONGLONG nPosition,
		int nParagraph, int nChar,LPCSTR Message, LPCSTR ConcMsg))
	{
		NotifyError = Handler;
	}
protected:
	void InitializeOutput();
	void FinalizeOutput();
	BOOL Parse(CStringA FileName);
	BOOL CommandBlock();
	BOOL Paragraph();
	BOOL Embeded();
	BOOL Command();
	BOOL Character();
	BOOL Justify(char Just);
	BOOL Bold();
	BOOL Font();
	BOOL Header();
	BOOL Footer();
	BOOL Table();
	BOOL Footnote();
	BOOL PageAdvance();
	BOOL PageNumber();
	BOOL PageNumberCode();
	BOOL TableParagraph();

	// Error Handling
	BOOL Error(MPError nError, LPCSTR ConcMsg = NULL);
	static BOOL DefaultHandle (MPError nError, LPCSTR Filename, ULONGLONG nPosition,
		int nParagraph, int nChar,LPCSTR Message, LPCSTR ConcMsg);
	BOOL CommandError(MPError nError);
	BOOL HeaderFooterError(BOOL bHeader, EmbedType OldEmbed);
	BOOL TableParaError(BOOL bDelimiter, EmbedType OldEmbed, CRichWriter::RichJust OldJust);
	// Error Message Ready
	CMLSScanner::MLSToken GetTokenForCommand();
	void SkipCommand();

protected:
	BOOL (*NotifyError) (MPError nError, LPCSTR Filename, ULONGLONG nPosition,
		int nParagraph, int nChar,LPCSTR Message, LPCSTR ConcMsg);
	CStringA LastCommand;
	static BOOL bIgnorError;

	BOOL IsEndOfCommand();
	BOOL IsEndOfParagraph();
	BOOL IsDigit();
	int ParseInt();
	BOOL Comma();
	void SkipWhiteSpaces();
	EmbedType Embed;
	TableColumn Column[MAX_TBLCOLS];
	CRichWriter::RichJust CurrentJust;
	//CStringA ErrorText;
	CRichWriter* Output;
	//MPError Error;
	CStringA CurrentFile;
	char PageCode;
	static CStringA ErrMsg[];
	static char JustComChar[5];
	static CommandRulesItem MLSCommandRules[MAX_COMM];

	// Language Setup
	int Roman;
	int Arabic;
	int Coptic;
	int Greek;


	int CurrentLang;
	int ArabicFont;
	int CopticFont;
	int EnglishFont;
	int GreekFont;
	BOOL Underline;
	BOOL bTaleDefined;
	int TotalWidth;
	int ColCount;

	COLORREF TextColor;
	COLORREF CommandsColor;
	COLORREF SeparatorColor;
	BOOL bGenerateSeparator;
};
